package com.boot.Bean;

import com.boot.annoation.Bean;
import com.boot.annoation.Di;

import java.io.File;
import java.lang.reflect.Field;
import java.net.URL;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;

public class AnnotationApplicationContext implements ApplicationConText {
    // 1、创建一个储存的集合Map
    private final Map<Class, Object> beanFactory = new HashMap<>();
    private static String rootPath;

    //2、实现方法，返回对象
    @Override
    public Object getBean(Class clazz) {
        return beanFactory.get(clazz);
    }

    //3、设置包扫描规则，哪个类有@bean注解，把这个类反射实例化
    public AnnotationApplicationContext(String basePackages) {
        String packagePath = getPath(basePackages);
        if (packagePath != null) {
            loadBean(packagePath);
        }
    }

    public void loadBean(String path) {
        File file = new File(path);
            if (file.isDirectory()) {
                File[] childrenFiles = file.listFiles();
                if (childrenFiles != null) {
                    for (File child : childrenFiles) {
                        if (child.isDirectory()) {
                            loadBean(child.getAbsolutePath());
                        } else {
                            String formatPath = child.getAbsolutePath()
                                    .substring(rootPath.length() - 1);
                            addToMap(formatPath);
                        }
                    }
                }
            } else {
                addToMap(file.getAbsolutePath().substring(rootPath.length() - 1));
            }
        loadDi();
    }

    public void loadDi() {
        for(Map.Entry<Class, Object> entry : beanFactory.entrySet()) {
            Object obj = entry.getValue();
            Class<?> clazz = obj.getClass();
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {
                Di annotation = field.getAnnotation(Di.class);
                if (annotation != null) {
                    field.setAccessible(true);
                }
                try {
                    field.set(obj, beanFactory.get(field.getType()));
                } catch (IllegalAccessException e) {
                    throw new RuntimeException(e.getMessage());
                }
            }
        }
    }

    public void addToMap(String path) {
        if (path.endsWith(".class")) {
            String fullName = path.replace(".class", "").replace("\\", ".");
            try {
                Class<?> clazz = Class.forName(fullName);
                if (!clazz.isInterface()) {
                    Object instance = clazz.getDeclaredConstructor().newInstance();
                    Bean beanAnnotation = clazz.getAnnotation(Bean.class);
                    if (beanAnnotation != null) {
                        if (clazz.getInterfaces().length > 0) {
                            beanFactory.put(clazz.getInterfaces()[0], instance);
                        } else {
                            beanFactory.put(clazz, instance);
                        }
                    }

                }
            } catch (Exception e) {
                throw new RuntimeException(e.getMessage());
            }
        }
    }

    public String getPath(@org.jetbrains.annotations.NotNull String basePackage) {
        // 1、把路径转换为标准格式
        String packagePath = basePackage.replaceAll("\\.", "/");
        // 2、把路径转换为标准格式
        try {
            URL url = Thread.currentThread().getContextClassLoader().getResource(packagePath);
            String path = null;
            if (url != null) {
                path = url.getPath();
            }
            if (path != null) {
                rootPath = path.substring(0, path.length() - basePackage.length());
            }
            return path;
        } catch (NullPointerException e) {
            throw new RuntimeException(e.getMessage());
        }
    }
}
